﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Web;
using System.IO;
using System.Xml.Serialization;
using System.CodeDom.Compiler;
using System.Reflection;
using System.Web.Script.Serialization;

using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization.Formatters.Soap;
using System.Runtime.Serialization.Json;

using System.Data;
using System.ComponentModel;
using System.Web.Security;
using System.Xml.XPath;
using System.Xml;
using System.Xml.Xsl;
using System.Runtime.Serialization.Formatters.Binary;
using System.Diagnostics.CodeAnalysis;
using System.Xml.Linq;

namespace WebeTerm.Common
{
    public static class Utility
    {
        public static string GetValue(Dictionary<string, object> paras, string paraName)
        {
            IEnumerable<KeyValuePair<string, object>> para = paras.Where(it => it.Key == paraName);
            if (para.Count() == 0) return null;
            return Convert.ToString(para.FirstOrDefault().Value);
        }

        public static string BuildHtml(string result)
        {
            result = String.Format("<div class='hrpform'>{0}</div>", result);
            return result;
        }


        /// <summary>
        /// 金额误差计算
        /// </summary>
        /// <param name="money"></param>
        /// <returns></returns>
        public static decimal MoneyRoundUp(this decimal money) {
            if (Math.Ceiling(money * 100) == money * 100) return money;
            return Math.Round(money+0.005m,2);
        }


        /// <summary>
        /// 获取MD5密码串
        /// </summary>
        /// <param name="Str"></param>
        /// <returns></returns>
        public static string MD5(string Str)
        {
            return FormsAuthentication.HashPasswordForStoringInConfigFile(Str, "MD5");
        }

        public static Guid ParseGuid(string str)
        {
            try
            {
                return Guid.Parse(str);
            }
            catch
            {
                return Guid.Empty;
            }
        }

        /// <summary>
        /// 将字符串转换为Guid
        /// </summary>
        /// <param name="str"></param>
        /// <returns>Guid</returns>
        public static Guid? ParseGuidNull(string str)
        {
            try
            {
                return Guid.Parse(str);
            }
            catch
            {
                return null;
            }
        }
        /// <summary>
        /// 将字符串转换为日期类型
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>日期</returns>
        public static DateTime? ParseDate(string str)
        {
            DateTime result;

            if (DateTime.TryParse(str, out result))
            {
                return result;
            }
            else
            {
                return null;
            }
        }

        /// <summary>
        /// 获取指定日期的开始时间
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public static DateTime ParseBeginTime(DateTime date)
        {
            return DateTime.Parse(date.ToShortDateString() + " " + "00:00:00");
        }

        /// <summary>
        /// 获取指定日期的结束时间
        /// </summary>
        /// <param name="date"></param>
        /// <returns></returns>
        public static DateTime ParseEndTime(DateTime date)
        {
            return DateTime.Parse(date.ToShortDateString() + " " + "23:59:59");
        }

        /// <summary>
        /// 将字符串转换为小数类型
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>小数</returns>
        public static decimal? ParseDecimal(string str)
        {
            decimal result;
            return decimal.TryParse(str, out result) ? result as decimal? : null;
        }

        public static double? Parsedouble(string str)
        {
            double result;
            return double.TryParse(str, out result) ? result as double? : null;
        }

        /// <summary>
        /// 将字符串转换为整数类型
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>整数</returns>
        public static int? ParseInt(string str)
        {
            int result;
            return int.TryParse(str, out result) ? result as int? : null;
        }

        /// <summary>
        /// 将字符串转换为无符号整数类型
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>整数</returns>
        public static byte? ParseByte(string str)
        {
            byte result;
            return byte.TryParse(str, out result) ? result as byte? : null;
        }

        /// <summary>
        /// 将字符串转换为布尔类型
        /// </summary>
        /// <param name="str">字符串</param>
        /// <returns>布尔</returns>
        public static bool? ParseBool(string str)
        {
            if (string.IsNullOrEmpty(str))
            {
                return null;
            }

            return str == "1"||str.ToLower()==@"true";
        }

        /// <summary>
        /// 获取格式化布尔值(钩/叉)
        /// </summary>
        /// <param name="data">待格式化的内容</param>
        /// <returns>格式化后的内容</returns>
        public static string FormatBool(object data)
        {
            if (Convert.ToBoolean(data))
            {
                return "<div class='yes' title='是'>&nbsp;</div>";
            }
            else
            {
                return "<div class='no' title='否'>&nbsp;</div>";
            }
        }

        /// <summary>
        /// 获取格式化布尔值(钩)
        /// </summary>
        /// <param name="data">待格式化的内容</param>
        /// <returns>格式化后的内容</returns>
        public static string FormatBool2(object data)
        {
            if (Convert.ToBoolean(data))
            {
                return "<font size=3 face='wingdings 2'>P</font>";
            }
            else
            {
                return string.Empty;
            }
        }

        /// <summary>
        /// 获取格式化布尔值(是/否)
        /// </summary>
        /// <param name="data">待格式化的内容</param>
        /// <returns>格式化后的内容</returns>
        public static string FormatBool3(object data)
        {
            if (Convert.ToBoolean(data))
            {
                return "是";
            }
            else
            {
                return "否";
            }
        }

        /// <summary>
        /// 获取格式化日期
        /// </summary>
        /// <param name="obj">日期</param>
        /// <returns>格式化后的日期</returns>
        public static string FormatDate(object obj)
        {
            if (obj == null || Convert.ToDateTime(obj).Year == 1)
            {
                return string.Empty;
            }
            else
            {
                return Convert.ToDateTime(obj).ToString("yyyy-MM-dd");
            }
        }

        /// <summary>
        /// 获取格式化日期时间
        /// </summary>
        /// <param name="obj">日期时间</param>
        /// <returns>格式化后的日期时间</returns>
        public static string FormatDateTime(object obj)
        {
            if (obj == null || Convert.ToDateTime(obj).Year == 1)
            {
                return string.Empty;
            }
            else
            {
                return Convert.ToDateTime(obj).ToString("yyyy-MM-dd HH:mm");
            }
        }

        /// <summary>
        /// 获取格式化内容
        /// </summary>
        /// <param name="longString">内容</param>
        /// <param name="length">截取后的长度</param>
        /// <returns>格式化后的内容</returns>
        public static string FormatLongString(object longString, int length)
        {
            if (longString == null)
                return "";
            string str = longString as string;
            if (str.Length > length)
            {
                return str.Remove(length) + "...";
            }
            else
            {
                return str;
            }
        }

        /// <summary>
        /// 获取格式化整数
        /// </summary>
        /// <param name="obj">数值</param>
        /// <returns>格式化后的金额</returns>
        public static string FormatInt(object obj)
        {
            return Convert.ToInt32(obj).ToString("#,##0");
        }

        /// <summary>
        /// 获取格式化金额
        /// </summary>
        /// <param name="obj">金额</param>
        /// <returns>格式化后的金额</returns>
        public static string FormatMoney(object obj)
        {
            
            return FormatMoney(obj,@"#,##0.00");
        }

        /// <summary>
        /// 获取格式化金额
        /// </summary>
        /// <param name="obj">金额</param>
        /// <returns>格式化后的金额</returns>
        public static string FormatMoney(object obj, string moneyFormat ) {
            if (obj == null)
                return "--";
            return Convert.ToDecimal(obj).ToString(moneyFormat);
        }

        /// <summary>
        /// 获取格式化金额
        /// </summary>
        /// <param name="obj">金额</param>
        /// <returns>格式化后的金额</returns>
        public static string FormatMoneyEdit(object obj)
        {
            return Convert.ToDecimal(obj).ToString("0.##");
        }

        /// <summary>
        /// 获取格式化Title
        /// </summary>
        /// <param name="obj">内容</param>
        /// <returns>格式化后的内容</returns>
        public static string FormatTitle(object obj)
        {
            if (obj == null)
            {
                return string.Empty;
            }
            else
            {
                return HttpUtility.HtmlDecode(obj.ToString()).Replace("<br>", "\r\n");
            }
        }

        /// <summary>
        /// 返回空链接
        /// </summary>        
        public static string AnchorHrefNull()
        {
            return "javascript:;";
        }

        /// <summary>
        /// 将服务端虚拟路径设置为绝对路径
        /// </summary>
        /// <param name="urlObj"></param>
        /// <returns></returns>
        public static string GetAbsoluteUrl(object urlObj)
        {
            string nullUrl = AnchorHrefNull();
            string url = urlObj as string;

            if (string.IsNullOrEmpty(url))
                return nullUrl;
            try
            {
                if (!url.ToLower().StartsWith(@"http://"))
                    return System.Web.VirtualPathUtility.ToAbsolute(url);
                else
                    return url;
            }
            catch
            {
                return nullUrl;
            }
        }

        public static string GetAppVirtualPath(string path)
        {
            string url = "http://";
            url += System.Web.HttpContext.Current.Request.Url.Host;
            if (System.Web.HttpContext.Current.Request.Url.Port != 80)
            {
                url += ":" + System.Web.HttpContext.Current.Request.Url.Port + "/";
            }
            else
            {
                url += "/";
            }
            return url + path;
        }



        /// <summary>
        /// 计算md5加密Token
        /// </summary>
        public static string CalUserMd5Token(string userName)
        {
            //按用户名，当前天计算md5的token。
            string token = System.Web.Security.FormsAuthentication.HashPasswordForStoringInConfigFile(userName.ToLower() + DateTime.Now.Day.ToString(), "MD5");
            return token;
        }

        /// <summary>
        /// 获得物理路径
        /// </summary>
        /// <param name="path"></param>
        /// <returns></returns>
        public static string GetMapPath(string path)
        {
            return System.Web.HttpContext.Current.Request.MapPath(path);
        }

        public static string FormatBankAccount(string account)
        {
            if (account != null)
                if (account.Length >= 8)
                {
                    string formatAccount = account.Substring(0, 4) + "****" + account.Substring(account.Length < 4 ? 0 : account.Length - 4);
                    return formatAccount;
                }
            return account;
        }

        /// <summary>
        /// 获取指定date的月份包含几个自然周
        /// </summary>
        /// <param name="date">日期</param>
        /// <returns>自然周数量</returns>
        public static int GetWeekCount(DateTime date)
        {
            date = new DateTime(date.Year, date.Month, 1);
            DayOfWeek monday = DayOfWeek.Monday;
            DateTime temp = date;
            int count = 0;
            int j = 1;
            if (temp.DayOfWeek != monday)
            {
                count++;
            }
            for (int i = 1; i <= 31; )
            {
                if (temp.Month > date.Month)
                    break;
                if (temp.DayOfWeek == monday && temp.Month == date.Month)
                {
                    i = i + 7;
                    j = 7;
                    count++;
                }
                else
                {
                    i++;
                    j = 1;
                }
                temp = temp.AddDays(j);
            }
            if (temp.Month > date.Month)
            {
                temp = temp.AddDays(-7);
                if (temp.DayOfWeek != monday)
                    count++;
            }
            return count;
        }


        public static object GetPropertyValue(this object obj, string propertyName) {
            return obj.GetType().GetProperty(propertyName).GetValue(obj, null);
        }

        public static int GetWeekCount(DateTime date, DayOfWeek dow)
        {
            date = new DateTime(date.Year, date.Month, 1);
            DateTime temp = date;
            int count = 0;
            int j = 1;
            if (temp.DayOfWeek != dow)
            {
                count++;
            }
            for (int i = 1; i <= 31; )
            {
                if (temp.Month > date.Month)
                    break;
                if (temp.DayOfWeek == dow && temp.Month == date.Month)
                {
                    i = i + 7;
                    j = 7;
                    count++;
                }
                else
                {
                    i++;
                    j = 1;
                }
                temp = temp.AddDays(j);
            }
            if (temp.Month > date.Month)
            {
                temp = temp.AddDays(-7);
                if (temp.DayOfWeek != dow)
                    count++;
            }
            return count;
        }

        public static int GetWeekIndex(DateTime date)
        {
            DateTime temp = date;
            int total = GetWeekCount(temp);
            int i = 1;
            while (true)
            {
                temp = date;
                DateTime begin = GetIndexWeekDate(temp, i);
                DateTime end = begin.AddDays(6);
                if (date >= begin && date <= end)
                {
                    break;
                }
                i++;
            }
            return i;
        }
        /// <summary>
        /// 获得当前日期在第几周
        /// </summary>
        /// <param name="date"></param>
        /// <param name="dow"></param>
        /// <returns></returns>
        public static int GetWeekIndex(DateTime date, DayOfWeek dow)
        {
            DateTime temp = date;
            int total = GetWeekCount(temp);
            int i = 1;
            while (true)
            {
                temp = date;
                DateTime begin = GetIndexWeekDate(temp, i, dow);
                DateTime end = begin.AddDays(6);
                if (date >= begin && date <= end)
                {
                    break;
                }
                i++;
            }
            return i;
        }

        /// <summary>
        /// 获取指定date的月份第index周的开始日期
        /// </summary>
        /// <param name="date"></param>
        /// <param name="index"></param>
        /// <returns></returns>
        public static DateTime GetIndexWeekDate(DateTime date, int index)
        {
            DateTime begin = new DateTime(date.Year, date.Month, 1);
            while (begin.DayOfWeek != DayOfWeek.Monday)
            {
                begin = begin.AddDays(-1);
            }
            int days = (index - 1) * 7;
            begin = begin.AddDays(days);
            return begin;
        }

        /// <summary>
        /// 获取指定date的月份第index周的开始日期
        /// </summary>
        /// <param name="date"></param>
        /// <param name="index"></param>
        /// <param name="dow"></param>
        /// <returns></returns>
        public static DateTime GetIndexWeekDate(DateTime date, int index, DayOfWeek dow)
        {
            DateTime begin = new DateTime(date.Year, date.Month, 1);
            while (begin.DayOfWeek != dow)
            {
                begin = begin.AddDays(-1);
            }
            int days = (index - 1) * 7;
            begin = begin.AddDays(days);
            return begin;
        }

        public static string GetWeekName(DayOfWeek day)
        {
            if (day == DayOfWeek.Monday)
            {
                return "星期一";
            }
            if (day == DayOfWeek.Tuesday)
            {
                return "星期二";
            }
            if (day == DayOfWeek.Wednesday)
            {
                return "星期三";
            }
            if (day == DayOfWeek.Thursday)
            {
                return "星期四";
            }
            if (day == DayOfWeek.Friday)
            {
                return "星期五";
            }
            if (day == DayOfWeek.Saturday)
            {
                return "星期六";
            }
            if (day == DayOfWeek.Sunday)
            {
                return "星期日";
            }
            return "";
        }


        public static string RemoveChar(string str, char c)
        {
            if (str.StartsWith(c.ToString()))
            {
                str = str.Remove(0, 1);
            }
            return str;
        }


        /// <summary>
        /// 序列化对象
        /// </summary>
        /// <param name="obj">对象</param>
        /// <returns>xml字符串</returns>
        public static string Serialize(object obj)
        {
            if (obj == null)
                return null;

            using (MemoryStream stream = new MemoryStream())
            {
                XmlSerializer xs = new XmlSerializer(obj.GetType());
                xs.Serialize(stream, obj);
                return UTF8Encoding.UTF8.GetString(stream.ToArray());
            }
        }

        /// <summary>
        /// 序列化对象
        /// </summary>
        public static string Serialize<T>(T t)
        {
            if (t == null)
                return null;

            using (MemoryStream stream = new MemoryStream())
            {
                XmlSerializer xs = new XmlSerializer(t.GetType());
                xs.Serialize(stream, t);
                return UTF8Encoding.UTF8.GetString(stream.ToArray());
            }
        }

        /// <summary>
        /// 将XML反序列化为对象
        /// </summary>
        public static object Deserialize(Type type, string xml)
        {
            if (string.IsNullOrEmpty(xml) || xml == "null")
                return null;
            using (StringReader sr = new StringReader(xml))
            {
                XmlSerializer xz = new XmlSerializer(type);
                return xz.Deserialize(sr);
            }
        }

        public static string JsSerializer(object obj)
        {
            JavaScriptSerializer jss = new JavaScriptSerializer();
            return jss.Serialize(obj);
        }

        /// <summary>
        /// 获取动态代码结果值
        /// </summary>
        /// <param name="expression">表达式</param>
        /// <returns>结果值</returns>
        public static object Eval(string expression)
        {
            string className = "EvalClass";
            string methodName = "EvalMethod";

            // 创建编译器实例
            CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp");

            // 设置编译参数
            CompilerParameters parameters = new CompilerParameters();

            parameters.GenerateExecutable = false;
            parameters.GenerateInMemory = true;

            // 创建动态代码。      
            StringBuilder classSource = new StringBuilder();
            classSource.Append("using System;\n");
            classSource.Append("\n");
            classSource.Append("public class " + className + "\n");
            classSource.Append("{\n");
            classSource.Append("	public object " + methodName + "()\n");
            classSource.Append("	{\n");
            classSource.Append("		return " + expression + ";\n");
            classSource.Append("	}\n");
            classSource.Append("}");

            // 编译代码
            CompilerResults result = provider.CompileAssemblyFromSource(parameters, classSource.ToString());

            // 获取编译后的程序集
            Assembly assembly = result.CompiledAssembly;

            // 动态调用方法
            object eval = assembly.CreateInstance(className);
            MethodInfo method = eval.GetType().GetMethod(methodName);
            object obj = method.Invoke(eval, null);

            GC.Collect();

            return obj;
        }

        /// <summary>
        /// 获取两个字符之间的字符串
        /// </summary>
        /// <param name="source">字符串内容</param>
        /// <param name="symbol1">第一个字符</param>
        /// <param name="symbol2">第二个字符</param>
        /// <returns>两个字符之间的字符串</returns>
        public static string Substring(string source, char symbol1, char symbol2)
        {
            int index1 = source.IndexOf(symbol1);
            int index2 = source.IndexOf(symbol2);

            if (index1 == -1 || index2 == -1 || index1 > index2)
            {
                return null;
            }

            return source.Substring(index1 + 1, index2 - index1 - 1);
        }

        /// <summary>
        /// 装传进来的二进制内容保存为文件
        /// </summary>
        /// <param name="path">需要保存的位置路径</param>
        /// <param name="content">需要转换的二进制内容</param>
        public static void BinaryToFile(string path, byte[] content)
        {
            using (FileStream fs = new FileStream(path, FileMode.Create, FileAccess.Write))
            {
                BinaryWriter bw = new BinaryWriter(fs);
                bw.Write(content);
                bw.Close();
                bw.Dispose();
                fs.Close();
            }
        }

        /// <summary>
        /// 数字转换为中文大写
        /// </summary>
        /// <param name="num">要转换的数字</param>
        /// <returns></returns>
        public static string NumToChinese(double num)
        {
            NumberToChinese ntc = new NumberToChinese(num);
            return ntc.Convert();
        }



        /// < summary>
        /// 将xml转化为html
        /// < /summary>
        public static string XmlTransToHtml(string xmlStream, byte[] xslFileContent)
        {
            //生成Html文件路径
            //string HtmlFilePath = htmlFilePath;
            MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(xmlStream));
            XPathDocument myXPathDoc = new XPathDocument(ms);
            XslCompiledTransform myXslTrans = new XslCompiledTransform();
            using (MemoryStream fileMs = new MemoryStream(xslFileContent))
            {
                XmlReader xr = XmlReader.Create(fileMs);
                myXslTrans.Load(xr);

                MemoryStream st = new MemoryStream();

                XmlTextWriter myWriter = new XmlTextWriter(st, System.Text.Encoding.UTF8);
                myXslTrans.Transform(myXPathDoc, null, myWriter);
                myWriter.Close();
                return Encoding.UTF8.GetString(st.ToArray());
            }
        }

        /// < summary>
        ///将xml转化为html
        /// < /summary>
        /// < param name="XmlPath">xml文件流< /param>
        /// < param name="XslFilePath">xslt文件路径< /param>
        /// < param name="htmlFilePath">声称的html文件路径< /param>
        public static string XmlTransToHtml(string xmlStream, string xslFilePath)
        {
            //生成Html文件路径
            //string HtmlFilePath = htmlFilePath;
            MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(xmlStream));
            XPathDocument myXPathDoc = new XPathDocument(ms);
            XslCompiledTransform myXslTrans = new XslCompiledTransform();

            //加载XSL文件
            myXslTrans.Load(xslFilePath);

            MemoryStream st = new MemoryStream();

            XmlTextWriter myWriter = new XmlTextWriter(st, System.Text.Encoding.GetEncoding(@"gb2312"));
            myXslTrans.Transform(myXPathDoc, null, myWriter);
            myWriter.Close();
            return Encoding.Default.GetString(st.ToArray());
        }


        /// <summary>
        /// 获取枚举类子项描述信息
        /// </summary>
        /// <param name="enumSubitem">枚举类子项</param>        
        public static string GetEnumDescription(Enum enumSubitem)
        {
            string strValue = enumSubitem.ToString();

            FieldInfo fieldinfo = enumSubitem.GetType().GetField(strValue);
            Object[] objs = fieldinfo.GetCustomAttributes(typeof(DescriptionAttribute), false);
            if (objs == null || objs.Length == 0)
            {
                return strValue;
            }
            else
            {
                DescriptionAttribute da = (DescriptionAttribute)objs[0];
                return da.Description;
            }

        }


        #region 序列货
        /// <summary>
        /// Serializes object to bytes.
        /// </summary>
        /// <param name="source">Source object.</param>
        /// <returns>Byte array.</returns>
        public static byte[] SerializeBinary(this object source)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            BinaryFormatter binaryFormatter = new BinaryFormatter();

            using (MemoryStream memoryStream = new MemoryStream())
            {
                binaryFormatter.Serialize(memoryStream, source);
                memoryStream.Position = 0;
                return memoryStream.ToArray();
            }
        }

        /// <summary>
        /// Serializes object to bytes, write to file.
        /// </summary>
        /// <param name="source">Source object.</param>
        /// <param name="filename">File name.</param>
        /// <param name="overwrite">Whether overwrite exists file.</param>
        /// <returns>File full path.</returns>
        public static string WriteBinary(this object source, string filename, bool overwrite = false)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (string.IsNullOrEmpty(filename))
            {
                throw new ArgumentNullException("filename");
            }

            string fullPath = Path.GetFullPath(filename);
            string fullDirectoryPath = Path.GetDirectoryName(fullPath);

            if (!overwrite && File.Exists(filename))
            {
                throw new ArgumentException("The specified file already exists.", fullPath);
            }

            if (!Directory.Exists(fullDirectoryPath))
            {
                try
                {
                    Directory.CreateDirectory(fullDirectoryPath);
                }
                catch
                {
                    throw;
                }
            }

            BinaryFormatter binaryFormatter = new BinaryFormatter();

            using (FileStream fileStream = File.OpenWrite(fullPath))
            {
                binaryFormatter.Serialize(fileStream, source);
                return fullPath;
            }
        }

        /// <summary>
        /// Deserializes bytes to object.
        /// </summary>
        /// <param name="source">Byte array.</param>
        /// <returns>Instance object.</returns>
        public static object DeserializeBinary(this byte[] source)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (source.Length == 0)
            {
                throw new ArgumentOutOfRangeException("source");
            }

            BinaryFormatter binaryFormatter = new BinaryFormatter();

            using (MemoryStream memoryStream = new MemoryStream(source))
            {
                memoryStream.Position = 0;
                return binaryFormatter.Deserialize(memoryStream);
            }
        }

        /// <summary>
        /// Deserializes bytes to object, read from file.
        /// </summary>
        /// <param name="source">File name.</param>
        /// <returns>Instance object.</returns>
        public static object ReadBinary(this string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            string fullPath = Path.GetFullPath(source);

            if (!File.Exists(fullPath))
            {
                throw new FileNotFoundException("The specified file does not exist.", fullPath);
            }

            BinaryFormatter binaryFormatter = new BinaryFormatter();

            using (FileStream fileStream = File.OpenRead(fullPath))
            {
                return binaryFormatter.Deserialize(fileStream);
            }
        }

        /// <summary>
        /// Deserializes bytes to object.
        /// </summary>
        /// <typeparam name="T">The type of returns object.</typeparam>
        /// <param name="source">Byte array.</param>
        /// <returns>Instance of T.</returns>
        public static T DeserializeBinary<T>(this byte[] source)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (source.Length == 0)
            {
                throw new ArgumentOutOfRangeException("source");
            }

            BinaryFormatter binaryFormatter = new BinaryFormatter();

            using (MemoryStream memoryStream = new MemoryStream(source))
            {
                memoryStream.Position = 0;
                return (T)binaryFormatter.Deserialize(memoryStream);
            }
        }

        /// <summary>
        /// Deserializes bytes to object, read from file.
        /// </summary>
        /// <typeparam name="T">The type of returns object.</typeparam>
        /// <param name="source">File name.</param>
        /// <returns>Instance of T.</returns>
        public static T ReadBinary<T>(this string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            string fullPath = Path.GetFullPath(source);

            if (!File.Exists(fullPath))
            {
                throw new FileNotFoundException("The specified file does not exist.", fullPath);
            }

            BinaryFormatter binaryFormatter = new BinaryFormatter();

            using (FileStream fileStream = File.OpenRead(fullPath))
            {
                return (T)binaryFormatter.Deserialize(fileStream);
            }
        }

        /// <summary>
        /// Serializes object to Xml string.
        /// </summary>
        /// <remarks>
        /// The object to be serialized should be decorated with the <see cref="SerializableAttribute"/>, or implement the <see cref="ISerializable"/> interface.
        /// </remarks>
        /// <param name="source">The object to serialize.</param>
        /// <param name="indent">Whether to write individual elements on new lines and indent.</param>
        /// <param name="omitXmlDeclaration">Whether to write an Xml declaration.</param>
        /// <param name="removeDefaultNamespace">Whether to write default namespace.</param>
        /// <param name="extraTypes">A <see cref="T:System.Type" /> array of additional object types to serialize.</param>
        /// <returns>An Xml encoded string representation of the source object.</returns>
        public static string SerializeXml(this object source, bool indent = false, bool omitXmlDeclaration = true, bool removeDefaultNamespace = true, Type[] extraTypes = null)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            string result = null;

            StringBuilder stringBuilder = new StringBuilder();

            XmlSerializer xmlSerializer = (extraTypes == null || extraTypes.Length == 0) ? new XmlSerializer(source.GetType()) : new XmlSerializer(source.GetType(), extraTypes);

            using (XmlWriter xmlWriter = XmlWriter.Create(stringBuilder, new XmlWriterSettings() { OmitXmlDeclaration = omitXmlDeclaration, Indent = indent /*, Encoding = new System.Text.UTF8Encoding(false)*/ }))
            {
                if (removeDefaultNamespace)
                {
                    XmlSerializerNamespaces xmlns = new XmlSerializerNamespaces();
                    xmlns.Add(string.Empty, string.Empty);
                    xmlSerializer.Serialize(xmlWriter, source, xmlns);
                }
                else
                {
                    xmlSerializer.Serialize(xmlWriter, source);
                }

                result = stringBuilder.ToString();
            }

            return result;
        }

        /// <summary>
        /// Serializes object to Xml string, write to file.
        /// </summary>
        /// <remarks>
        /// The object to be serialized should be decorated with the <see cref="SerializableAttribute"/>, or implement the <see cref="ISerializable"/> interface.
        /// </remarks>
        /// <param name="source">The object to serialize.</param>
        /// <param name="filename">File name.</param>
        /// <param name="overwrite">Whether overwrite exists file.</param>
        /// <param name="indent">Whether to write individual elements on new lines and indent.</param>
        /// <param name="omitXmlDeclaration">Whether to write an Xml declaration.</param>
        /// <param name="removeDefaultNamespace">Whether to write default namespace.</param>
        /// <param name="extraTypes">A <see cref="T:System.Type" /> array of additional object types to serialize.</param>
        /// <returns>File full path.</returns>
        public static string WriteXml(this object source, string filename, bool overwrite = false, bool indent = true, bool omitXmlDeclaration = true, bool removeDefaultNamespace = true, Type[] extraTypes = null)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (string.IsNullOrEmpty(filename))
            {
                throw new ArgumentNullException("filename");
            }

            string fullPath = Path.GetFullPath(filename);
            string fullDirectoryPath = Path.GetDirectoryName(fullPath);

            if (!overwrite && File.Exists(filename))
            {
                throw new ArgumentException("The specified file already exists.", fullPath);
            }

            if (!Directory.Exists(fullDirectoryPath))
            {
                try
                {
                    Directory.CreateDirectory(fullDirectoryPath);
                }
                catch
                {
                    throw;
                }
            }

            XmlSerializer xmlSerializer = (extraTypes == null || extraTypes.Length == 0) ? new XmlSerializer(source.GetType()) : new XmlSerializer(source.GetType(), extraTypes);

            using (XmlWriter xmlWriter = XmlWriter.Create(fullPath, new XmlWriterSettings() { OmitXmlDeclaration = omitXmlDeclaration, Indent = indent /*, Encoding = new System.Text.UTF8Encoding(false)*/ }))
            {
                if (removeDefaultNamespace)
                {
                    XmlSerializerNamespaces xmlns = new XmlSerializerNamespaces();
                    xmlns.Add(string.Empty, string.Empty);
                    xmlSerializer.Serialize(xmlWriter, source, xmlns);
                }
                else
                {
                    xmlSerializer.Serialize(xmlWriter, source);
                }

                return fullPath;
            }
        }

        /// <summary>
        /// Deserializes Xml string to object.
        /// </summary>
        /// <param name="source">The Xml string to deserialize.</param>
        /// <param name="type">Type of object.</param>
        /// <param name="extraTypes">A <see cref="T:System.Type" /> array of additional object types to serialize.</param>
        /// <returns>Instance of object.</returns>
        [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Reviewed.")]
        public static object DeserializeXml(this string source, Type type, Type[] extraTypes = null)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            XmlSerializer xmlSerializer = (extraTypes == null || extraTypes.Length == 0) ? new XmlSerializer(type) : new XmlSerializer(type, extraTypes);

            using (StringReader stringReader = new StringReader(source))
            {
                return xmlSerializer.Deserialize(stringReader);
            }
        }

        /// <summary>
        /// Deserializes Xml string to object.
        /// </summary>
        /// <param name="source">The Xml string to deserialize.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array of object types to serialize.</param>
        /// <returns>Instance of object.</returns>
        public static object DeserializeXml(this string source, Type[] knownTypes)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            if (knownTypes == null || knownTypes.Length < 1)
            {
                throw new ArgumentException("knownTypes is null or empty.", "knownTypes");
            }

            Type sourceType = null;

            using (StringReader stringReader = new StringReader(source))
            {
                string rootNodeName = XElement.Load(stringReader).Name.LocalName;

                sourceType = knownTypes.FirstOrDefault(p => p.Name.Equals(rootNodeName, StringComparison.OrdinalIgnoreCase));

                if (sourceType == null)
                {
                    throw new InvalidOperationException();
                }
            }

            XmlSerializer xmlSerializer = new XmlSerializer(sourceType, knownTypes);

            using (StringReader stringReader = new StringReader(source))
            {
                return xmlSerializer.Deserialize(stringReader);
            }
        }

        /// <summary>
        /// Deserializes Xml string to object, read from file.
        /// </summary>
        /// <param name="source">File name.</param>
        /// <param name="type">Type of object.</param>
        /// <param name="extraTypes">A <see cref="T:System.Type" /> array of additional object types to serialize.</param>
        /// <returns>Instance of object.</returns>
        public static object ReadXml(this string source, Type type, Type[] extraTypes = null)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            string fullPath = Path.GetFullPath(source);

            if (!File.Exists(fullPath))
            {
                throw new FileNotFoundException("The specified file does not exist.", fullPath);
            }

            XmlSerializer xmlSerializer = (extraTypes == null || extraTypes.Length == 0) ? new XmlSerializer(type) : new XmlSerializer(type, extraTypes);

            using (FileStream fileStream = File.OpenRead(fullPath))
            {
                return xmlSerializer.Deserialize(fileStream);
            }
        }

        /// <summary>
        /// Deserializes Xml string to object, read from file.
        /// </summary>
        /// <param name="source">File name.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array of object types to serialize.</param>
        /// <returns>Instance of object.</returns>
        public static object ReadXml(this string source, Type[] knownTypes)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            if (knownTypes == null || knownTypes.Length < 1)
            {
                throw new ArgumentException("knownTypes is null or empty.", "knownTypes");
            }

            string fullPath = Path.GetFullPath(source);

            if (!File.Exists(fullPath))
            {
                throw new FileNotFoundException("The specified file does not exist.", fullPath);
            }

            Type sourceType = null;

            string rootNodeName = XElement.Load(fullPath).Name.LocalName;

            sourceType = knownTypes.FirstOrDefault(p => p.Name.Equals(rootNodeName, StringComparison.OrdinalIgnoreCase));

            if (sourceType == null)
            {
                throw new InvalidOperationException();
            }

            XmlSerializer xmlSerializer = new XmlSerializer(sourceType, knownTypes);

            using (FileStream fileStream = File.OpenRead(fullPath))
            {
                return xmlSerializer.Deserialize(fileStream);
            }
        }

        /// <summary>
        /// Deserializes Xml string to object.
        /// </summary>
        /// <typeparam name="T">Type of the returns object.</typeparam>
        /// <param name="source">The Xml string to deserialize.</param>
        /// <param name="extraTypes">A <see cref="T:System.Type" /> array of additional object types to serialize.</param>
        /// <returns>Instance of T.</returns>
        [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Reviewed.")]
        public static T DeserializeXml<T>(this string source, Type[] extraTypes = null)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            XmlSerializer xmlSerializer = (extraTypes == null || extraTypes.Length == 0) ? new XmlSerializer(typeof(T)) : new XmlSerializer(typeof(T), extraTypes);

            using (StringReader stringReader = new StringReader(source))
            {
                return (T)xmlSerializer.Deserialize(stringReader);
            }
        }

        /// <summary>
        /// Deserializes Xml string to object, read from file.
        /// </summary>
        /// <typeparam name="T">Type of the returns object.</typeparam>
        /// <param name="source">File name.</param>
        /// <param name="extraTypes">A <see cref="T:System.Type" /> array of additional object types to serialize.</param>
        /// <returns>Instance of T.</returns>
        public static T ReadXml<T>(this string source, Type[] extraTypes = null)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            string fullPath = Path.GetFullPath(source);

            if (!File.Exists(fullPath))
            {
                throw new FileNotFoundException("The specified file does not exist.", fullPath);
            }

            XmlSerializer xmlSerializer = (extraTypes == null || extraTypes.Length == 0) ? new XmlSerializer(typeof(T)) : new XmlSerializer(typeof(T), extraTypes);

            using (FileStream fileStream = File.OpenRead(fullPath))
            {
                return (T)xmlSerializer.Deserialize(fileStream);
            }
        }

        /// <summary>
        /// Serializes object to Soap string.
        /// </summary>
        /// <param name="source">The object to serialize.</param>
        /// <returns>Soap string.</returns>
        public static string SerializeSoap(this object source)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            SoapFormatter soapFormatter = new SoapFormatter();

            using (MemoryStream memoryStream = new MemoryStream())
            {
                soapFormatter.Serialize(memoryStream, source);
                memoryStream.Position = 0;
                XmlDocument xmlDocument = new XmlDocument();
                xmlDocument.Load(memoryStream);
                return xmlDocument.InnerXml;
            }
        }

        /// <summary>
        /// Serializes object to Soap string, write to file.
        /// </summary>
        /// <param name="source">The object to serialize.</param>
        /// <param name="filename">File name.</param>
        /// <param name="overwrite">Whether overwrite exists file.</param>
        /// <returns>File full path.</returns>
        public static string WriteSoap(this object source, string filename, bool overwrite = false)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            string fullPath = Path.GetFullPath(filename);
            string fullDirectoryPath = Path.GetDirectoryName(fullPath);

            if (!overwrite && File.Exists(filename))
            {
                throw new ArgumentException("The specified file already exists.", fullPath);
            }

            if (!Directory.Exists(fullDirectoryPath))
            {
                try
                {
                    Directory.CreateDirectory(fullDirectoryPath);
                }
                catch
                {
                    throw;
                }
            }

            SoapFormatter soapFormatter = new SoapFormatter();

            using (FileStream fileStream = File.OpenWrite(fullPath))
            {
                soapFormatter.Serialize(fileStream, source);
                return fullPath;
            }
        }

        /// <summary>
        /// Deserializes Soap string to object.
        /// </summary>
        /// <param name="source">The Soap string to deserialize.</param>
        /// <returns>Instance of object.</returns>
        public static object DeserializeSoap(this string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(source);
            SoapFormatter soapFormatter = new SoapFormatter();

            using (MemoryStream memoryStream = new MemoryStream())
            {
                xmlDocument.Save(memoryStream);
                memoryStream.Position = 0;
                return soapFormatter.Deserialize(memoryStream);
            }
        }

        /// <summary>
        /// Deserializes Soap string to object, read from file.
        /// </summary>
        /// <param name="source">File name.</param>
        /// <returns>Instance of object.</returns>
        public static object ReadSoap(this string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            string fullPath = Path.GetFullPath(source);

            if (!File.Exists(fullPath))
            {
                throw new FileNotFoundException("The specified file does not exist.", fullPath);
            }

            SoapFormatter soapFormatter = new SoapFormatter();

            using (FileStream fileStream = File.OpenRead(fullPath))
            {
                return soapFormatter.Deserialize(fileStream);
            }
        }

        /// <summary>
        /// Deserializes Soap string to object.
        /// </summary>
        /// <typeparam name="T">Type of the returns object.</typeparam>
        /// <param name="source">The Soap string to deserialize.</param>
        /// <returns>Instance of T.</returns>
        public static T DeserializeSoap<T>(this string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(source);
            SoapFormatter soapFormatter = new SoapFormatter();

            using (MemoryStream memoryStream = new MemoryStream())
            {
                xmlDocument.Save(memoryStream);
                memoryStream.Position = 0;
                return (T)soapFormatter.Deserialize(memoryStream);
            }
        }

        /// <summary>
        /// Deserializes Soap string to object, read from file.
        /// </summary>
        /// <typeparam name="T">Type of the returns object.</typeparam>
        /// <param name="source">File name.</param>
        /// <returns>Instance of T.</returns>
        public static T ReadSoap<T>(this string source)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            string fullPath = Path.GetFullPath(source);

            if (!File.Exists(fullPath))
            {
                throw new FileNotFoundException("The specified file does not exist.", fullPath);
            }

            SoapFormatter soapFormatter = new SoapFormatter();

            using (FileStream fileStream = File.OpenRead(fullPath))
            {
                return (T)soapFormatter.Deserialize(fileStream);
            }
        }

        /// <summary>
        /// Serializes object to Json string.
        /// </summary>
        /// <param name="source">Object to serialize.</param>
        /// <param name="encoding">The encoding to apply to the string.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array that may be present in the object graph.</param>
        /// <returns>Json string.</returns>
        public static string SerializeJsonString(this object source, Encoding encoding = null, Type[] knownTypes = null)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            DataContractJsonSerializer dataContractJsonSerializer = (knownTypes == null || knownTypes.Length == 0) ? new DataContractJsonSerializer(source.GetType()) : new DataContractJsonSerializer(source.GetType(), knownTypes);

            using (MemoryStream memoryStream = new MemoryStream())
            {
                dataContractJsonSerializer.WriteObject(memoryStream, source);
                memoryStream.Position = 0;
                return (encoding ?? Encoding.UTF8).GetString(memoryStream.ToArray());
            }
        }

        /// <summary>
        /// Serializes object to Json string, write to file.
        /// </summary>
        /// <param name="source">Object to serialize.</param>
        /// <param name="filename">File name.</param>
        /// <param name="overwrite">Whether overwrite exists file.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array that may be present in the object graph.</param>
        /// <returns>File full path.</returns>
        public static string WriteJson(this object source, string filename, bool overwrite = false, Type[] knownTypes = null)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (string.IsNullOrEmpty(filename))
            {
                throw new ArgumentNullException("filename");
            }

            string fullPath = Path.GetFullPath(filename);
            string fullDirectoryPath = Path.GetDirectoryName(fullPath);

            if (!overwrite && File.Exists(filename))
            {
                throw new ArgumentException("The specified file already exists.", fullPath);
            }

            if (!Directory.Exists(fullDirectoryPath))
            {
                try
                {
                    Directory.CreateDirectory(fullDirectoryPath);
                }
                catch
                {
                    throw;
                }
            }

            DataContractJsonSerializer dataContractJsonSerializer = (knownTypes == null || knownTypes.Length == 0) ? new DataContractJsonSerializer(source.GetType()) : new DataContractJsonSerializer(source.GetType(), knownTypes);

            using (FileStream fileStream = File.OpenWrite(fullPath))
            {
                dataContractJsonSerializer.WriteObject(fileStream, source);
                return fullPath;
            }
        }

        /// <summary>
        /// Deserializes Json string to object.
        /// </summary>
        /// <param name="source">Json string object.</param>
        /// <param name="type">Type of object.</param>
        /// <param name="encoding">The encoding to apply to the string.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array that may be present in the object graph.</param>
        /// <returns>Instance of object.</returns>
        public static object DeserializeJsonString(this string source, Type type, Encoding encoding = null, Type[] knownTypes = null)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            DataContractJsonSerializer dataContractJsonSerializer = (knownTypes == null || knownTypes.Length == 0) ? new DataContractJsonSerializer(type) : new DataContractJsonSerializer(type, knownTypes);

            using (MemoryStream memoryStream = new MemoryStream((encoding ?? Encoding.UTF8).GetBytes(source)))
            {
                memoryStream.Position = 0;
                return dataContractJsonSerializer.ReadObject(memoryStream);
            }
        }

        /// <summary>
        /// Deserializes Json string to object.
        /// </summary>
        /// <param name="source">Json string object.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array of object types to serialize.</param>
        /// <param name="encoding">The encoding to apply to the string.</param>
        /// <returns>Instance of object.</returns>
        public static object DeserializeJsonString(this string source, Type[] knownTypes, Encoding encoding = null)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            if (knownTypes == null || knownTypes.Length < 1)
            {
                throw new ArgumentException("knownTypes is null or empty.", "knownTypes");
            }

            Type sourceType = null;

            using (StringReader stringReader = new StringReader(source))
            {
                string rootNodeName = XElement.Load(stringReader).Name.LocalName;

                sourceType = knownTypes.FirstOrDefault(p => p.Name == rootNodeName);

                if (sourceType == null)
                {
                    throw new InvalidOperationException();
                }
            }

            DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(sourceType, knownTypes);

            using (MemoryStream memoryStream = new MemoryStream((encoding ?? Encoding.UTF8).GetBytes(source)))
            {
                memoryStream.Position = 0;
                return dataContractJsonSerializer.ReadObject(memoryStream);
            }
        }

        /// <summary>
        /// Deserializes Json string to object, read from file.
        /// </summary>
        /// <param name="source">File name.</param>
        /// <param name="type">Type of object.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array that may be present in the object graph.</param>
        /// <returns>Instance of object.</returns>
        public static object ReadJson(this string source, Type type, Type[] knownTypes = null)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            string fullPath = Path.GetFullPath(source);

            if (!File.Exists(fullPath))
            {
                throw new FileNotFoundException("The specified file does not exist.", fullPath);
            }

            DataContractJsonSerializer dataContractJsonSerializer = (knownTypes == null || knownTypes.Length == 0) ? new DataContractJsonSerializer(type) : new DataContractJsonSerializer(type, knownTypes);

            using (FileStream fileStream = File.OpenRead(fullPath))
            {
                return dataContractJsonSerializer.ReadObject(fileStream);
            }
        }

        /// <summary>
        /// Deserializes Json string to object, read from file.
        /// </summary>
        /// <param name="source">File name.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array of object types to serialize.</param>
        /// <returns>Instance of object.</returns>
        public static object ReadJson(this string source, Type[] knownTypes = null)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            if (knownTypes == null || knownTypes.Length < 1)
            {
                throw new ArgumentException("knownTypes is null or empty.", "knownTypes");
            }

            string fullPath = Path.GetFullPath(source);

            if (!File.Exists(fullPath))
            {
                throw new FileNotFoundException("The specified file does not exist.", fullPath);
            }

            Type sourceType = null;

            string rootNodeName = XElement.Load(fullPath).Name.LocalName;

            sourceType = knownTypes.FirstOrDefault(p => p.Name == rootNodeName);

            if (sourceType == null)
            {
                throw new InvalidOperationException();
            }

            DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(sourceType, knownTypes);

            using (FileStream fileStream = File.OpenRead(fullPath))
            {
                return dataContractJsonSerializer.ReadObject(fileStream);
            }
        }

        /// <summary>
        /// Deserializes Json string to object.
        /// </summary>
        /// <typeparam name="T">Type of the returns objet.</typeparam>
        /// <param name="source">Json string object.</param>
        /// <param name="encoding">The encoding to apply to the string.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array that may be present in the object graph.</param>
        /// <returns>Instance of object.</returns>
        public static T DeserializeJsonString<T>(this string source, Encoding encoding = null, Type[] knownTypes = null)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            DataContractJsonSerializer dataContractJsonSerializer = (knownTypes == null || knownTypes.Length == 0) ? new DataContractJsonSerializer(typeof(T)) : new DataContractJsonSerializer(typeof(T), knownTypes);

            using (MemoryStream memoryStream = new MemoryStream((encoding ?? Encoding.UTF8).GetBytes(source)))
            {
                memoryStream.Position = 0;
                return (T)dataContractJsonSerializer.ReadObject(memoryStream);
            }
        }

        /// <summary>
        /// Deserializes Json string to object, read from file.
        /// </summary>
        /// <typeparam name="T">Type of the returns objet.</typeparam>
        /// <param name="source">File name.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array that may be present in the object graph.</param>
        /// <returns>Instance of object.</returns>
        public static T ReadJson<T>(this string source, Type[] knownTypes = null)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            string fullPath = Path.GetFullPath(source);

            if (!File.Exists(fullPath))
            {
                throw new FileNotFoundException("The specified file does not exist.", fullPath);
            }

            DataContractJsonSerializer dataContractJsonSerializer = (knownTypes == null || knownTypes.Length == 0) ? new DataContractJsonSerializer(typeof(T)) : new DataContractJsonSerializer(typeof(T), knownTypes);

            using (FileStream fileStream = File.OpenRead(fullPath))
            {
                return (T)dataContractJsonSerializer.ReadObject(fileStream);
            }
        }

        /// <summary>
        /// Serializes object to Json bytes.
        /// </summary>
        /// <param name="source">Object to serialize.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array that may be present in the object graph.</param>
        /// <returns>Json bytes.</returns>
        public static byte[] SerializeJsonBinary(this object source, Type[] knownTypes = null)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            DataContractJsonSerializer dataContractJsonSerializer = (knownTypes == null || knownTypes.Length == 0) ? new DataContractJsonSerializer(source.GetType()) : new DataContractJsonSerializer(source.GetType(), knownTypes);

            using (MemoryStream memoryStream = new MemoryStream())
            {
                dataContractJsonSerializer.WriteObject(memoryStream, source);
                memoryStream.Position = 0;
                return memoryStream.ToArray();
            }
        }

        /// <summary>
        /// Deserializes Json bytes to object.
        /// </summary>
        /// <param name="source">Json string object.</param>
        /// <param name="type">Type of object.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array that may be present in the object graph.</param>
        /// <returns>Instance of object.</returns>
        public static object DeserializeJsonBinary(this byte[] source, Type type, Type[] knownTypes = null)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            DataContractJsonSerializer dataContractJsonSerializer = (knownTypes == null || knownTypes.Length == 0) ? new DataContractJsonSerializer(type) : new DataContractJsonSerializer(type, knownTypes);

            using (MemoryStream memoryStream = new MemoryStream(source))
            {
                memoryStream.Position = 0;
                return dataContractJsonSerializer.ReadObject(memoryStream);
            }
        }

        /// <summary>
        /// Deserializes Json bytes to object.
        /// </summary>
        /// <param name="source">Json string object.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array of object types to serialize.</param>
        /// <returns>Instance of object.</returns>
        [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Reviewed.")]
        public static object DeserializeJsonBinary(this byte[] source, Type[] knownTypes)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (knownTypes == null || knownTypes.Length < 1)
            {
                throw new ArgumentException("knownTypes is null or empty.", "knownTypes");
            }

            Type sourceType = null;

            MemoryStream memoryStream = new MemoryStream(source);
            memoryStream.Position = 0;

            using (XmlReader xmlReader = XmlReader.Create(memoryStream))
            {
                string rootNodeName = XElement.Load(xmlReader).Name.LocalName;

                sourceType = knownTypes.FirstOrDefault(p => p.Name == rootNodeName);

                if (sourceType == null)
                {
                    throw new InvalidOperationException();
                }

                memoryStream.Position = 0;
                DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(sourceType, knownTypes);
                return dataContractJsonSerializer.ReadObject(memoryStream);
            }
        }

        /// <summary>
        /// Deserializes Json bytes to object.
        /// </summary>
        /// <typeparam name="T">Type of the returns objet.</typeparam>
        /// <param name="source">Json string object.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array that may be present in the object graph.</param>
        /// <returns>Instance of object.</returns>
        public static T DeserializeJsonBinary<T>(this byte[] source, Type[] knownTypes = null)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            DataContractJsonSerializer dataContractJsonSerializer = (knownTypes == null || knownTypes.Length == 0) ? new DataContractJsonSerializer(typeof(T)) : new DataContractJsonSerializer(typeof(T), knownTypes);

            using (MemoryStream memoryStream = new MemoryStream(source))
            {
                memoryStream.Position = 0;
                return (T)dataContractJsonSerializer.ReadObject(memoryStream);
            }
        }

        /// <summary>
        /// Serializes DataContract object to Xml string.
        /// </summary>
        /// <param name="source">The DataContract object to serialize.</param>
        /// <param name="indent">Whether to write individual elements on new lines and indent.</param>
        /// <param name="omitXmlDeclaration">Whether to write an Xml declaration.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array that may be present in the object graph.</param>
        /// <returns>An Xml encoded string representation of the source DataContract object.</returns>
        public static string SerializeDataContractXml(this object source, bool indent = false, bool omitXmlDeclaration = true, Type[] knownTypes = null)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            string result = null;

            StringBuilder stringBuilder = new StringBuilder();

            DataContractSerializer dataContractSerializer = (knownTypes == null || knownTypes.Length == 0) ? new DataContractSerializer(source.GetType()) : new DataContractSerializer(source.GetType(), knownTypes);

            using (XmlWriter xmlWriter = XmlWriter.Create(stringBuilder, new XmlWriterSettings() { OmitXmlDeclaration = omitXmlDeclaration, Indent = indent }))
            {
                dataContractSerializer.WriteObject(xmlWriter, source);
                xmlWriter.Flush();
                result = stringBuilder.ToString();
            }

            return result;
        }

        /// <summary>
        /// Serializes DataContract object to Xml string, write to file.
        /// </summary>
        /// <param name="source">The DataContract object to serialize.</param>
        /// <param name="filename">File name.</param>
        /// <param name="overwrite">Whether overwrite exists file.</param>
        /// <param name="indent">Whether to write individual elements on new lines and indent.</param>
        /// <param name="omitXmlDeclaration">Whether to write an Xml declaration.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array that may be present in the object graph.</param>
        /// <returns>File full path.</returns>
        public static string WriteDataContract(this object source, string filename, bool overwrite = false, bool indent = true, bool omitXmlDeclaration = true, Type[] knownTypes = null)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (string.IsNullOrEmpty(filename))
            {
                throw new ArgumentNullException("filename");
            }

            string fullPath = Path.GetFullPath(filename);
            string fullDirectoryPath = Path.GetDirectoryName(fullPath);

            if (!overwrite && File.Exists(filename))
            {
                throw new ArgumentException("The specified file already exists.", fullPath);
            }

            if (!Directory.Exists(fullDirectoryPath))
            {
                try
                {
                    Directory.CreateDirectory(fullDirectoryPath);
                }
                catch
                {
                    throw;
                }
            }

            DataContractSerializer dataContractSerializer = (knownTypes == null || knownTypes.Length == 0) ? new DataContractSerializer(source.GetType()) : new DataContractSerializer(source.GetType(), knownTypes);

            using (XmlWriter xmlWriter = XmlWriter.Create(fullPath, new XmlWriterSettings() { OmitXmlDeclaration = omitXmlDeclaration, Indent = indent }))
            {
                dataContractSerializer.WriteObject(xmlWriter, source);
                return fullPath;
            }
        }

        /// <summary>
        /// Deserializes DataContract Xml string to object.
        /// </summary>
        /// <param name="source">The DataContract Xml string to deserialize.</param>
        /// <param name="type">Type of DataContract object.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array that may be present in the object graph.</param>
        /// <returns>Instance of DataContract object.</returns>
        [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Reviewed.")]
        public static object DeserializeDataContractXml(this string source, Type type, Type[] knownTypes = null)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            DataContractSerializer dataContractSerializer = (knownTypes == null || knownTypes.Length == 0) ? new DataContractSerializer(type) : new DataContractSerializer(type, knownTypes);

            using (XmlReader xmlReader = XmlReader.Create(new StringReader(source), new XmlReaderSettings { CheckCharacters = false, IgnoreComments = true, IgnoreWhitespace = true, IgnoreProcessingInstructions = true }))
            {
                return dataContractSerializer.ReadObject(xmlReader);
            }
        }

        /// <summary>
        /// Deserializes DataContract Xml string to object.
        /// </summary>
        /// <param name="source">The DataContract Xml string to deserialize.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array of object types to serialize.</param>
        /// <returns>Instance of DataContract object.</returns>
        [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Reviewed.")]
        public static object DeserializeDataContractXml(this string source, Type[] knownTypes)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            if (knownTypes == null || knownTypes.Length < 1)
            {
                throw new ArgumentException("knownTypes is null or empty.", "knownTypes");
            }

            Type sourceType = null;

            using (StringReader stringReader = new StringReader(source))
            {
                string rootNodeName = XElement.Load(stringReader).Name.LocalName;

                sourceType = knownTypes.FirstOrDefault(p => p.Name == rootNodeName);

                if (sourceType == null)
                {
                    throw new InvalidOperationException();
                }
            }

            DataContractSerializer dataContractSerializer = new DataContractSerializer(sourceType, knownTypes);

            using (XmlReader xmlReader = XmlReader.Create(new StringReader(source), new XmlReaderSettings { CheckCharacters = false, IgnoreComments = true, IgnoreWhitespace = true, IgnoreProcessingInstructions = true }))
            {
                return dataContractSerializer.ReadObject(xmlReader);
            }
        }

        /// <summary>
        /// Deserializes DataContract Xml string to object, read from file.
        /// </summary>
        /// <param name="source">File name.</param>
        /// <param name="type">Type of DataContract object.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array that may be present in the object graph.</param>
        /// <returns>Instance of DataContract object.</returns>
        public static object ReadDataContract(this string source, Type type, Type[] knownTypes = null)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            string fullPath = Path.GetFullPath(source);

            if (!File.Exists(fullPath))
            {
                throw new FileNotFoundException("The specified file does not exist.", fullPath);
            }

            DataContractSerializer dataContractSerializer = (knownTypes == null || knownTypes.Length == 0) ? new DataContractSerializer(type) : new DataContractSerializer(type, knownTypes);

            using (FileStream fileStream = File.OpenRead(fullPath))
            {
                return dataContractSerializer.ReadObject(fileStream);
            }
        }

        /// <summary>
        /// Deserializes DataContract Xml string to object, read from file.
        /// </summary>
        /// <param name="source">File name.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array of object types to serialize.</param>
        /// <returns>Instance of DataContract object.</returns>
        public static object ReadDataContract(this string source, Type[] knownTypes)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            if (knownTypes == null || knownTypes.Length < 1)
            {
                throw new ArgumentException("knownTypes is null or empty.", "knownTypes");
            }

            string fullPath = Path.GetFullPath(source);

            if (!File.Exists(fullPath))
            {
                throw new FileNotFoundException("The specified file does not exist.", fullPath);
            }

            Type sourceType = null;

            string rootNodeName = XElement.Load(fullPath).Name.LocalName;

            sourceType = knownTypes.FirstOrDefault(p => p.Name == rootNodeName);

            if (sourceType == null)
            {
                throw new InvalidOperationException();
            }

            DataContractSerializer dataContractSerializer = new DataContractSerializer(sourceType, knownTypes);

            using (FileStream fileStream = File.OpenRead(fullPath))
            {
                return dataContractSerializer.ReadObject(fileStream);
            }
        }

        /// <summary>
        /// Deserializes DataContract Xml string to object.
        /// </summary>
        /// <typeparam name="T">Type of the returns object.</typeparam>
        /// <param name="source">The DataContract Xml string to deserialize.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array that may be present in the object graph.</param>
        /// <returns>Instance of T.</returns>
        [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Reviewed.")]
        public static T DeserializeDataContractXml<T>(this string source, Type[] knownTypes = null)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            DataContractSerializer dataContractSerializer = (knownTypes == null || knownTypes.Length == 0) ? new DataContractSerializer(typeof(T)) : new DataContractSerializer(typeof(T), knownTypes);

            using (XmlReader xmlReader = XmlReader.Create(new StringReader(source), new XmlReaderSettings { CheckCharacters = false, IgnoreComments = true, IgnoreWhitespace = true, IgnoreProcessingInstructions = true }))
            {
                return (T)dataContractSerializer.ReadObject(xmlReader);
            }
        }

        /// <summary>
        /// Deserializes DataContract Xml string to object, read from file.
        /// </summary>
        /// <typeparam name="T">Type of the returns object.</typeparam>
        /// <param name="source">File name.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array that may be present in the object graph.</param>
        /// <returns>Instance of T.</returns>
        public static T ReadDataContract<T>(this string source, Type[] knownTypes = null)
        {
            if (string.IsNullOrEmpty(source))
            {
                throw new ArgumentNullException("source");
            }

            string fullPath = Path.GetFullPath(source);

            if (!File.Exists(fullPath))
            {
                throw new FileNotFoundException("The specified file does not exist.", fullPath);
            }

            DataContractSerializer dataContractSerializer = (knownTypes == null || knownTypes.Length == 0) ? new DataContractSerializer(typeof(T)) : new DataContractSerializer(typeof(T), knownTypes);

            using (FileStream fileStream = File.OpenRead(fullPath))
            {
                return (T)dataContractSerializer.ReadObject(fileStream);
            }
        }

        /// <summary>
        /// Serializes DataContract object to bytes.
        /// </summary>
        /// <param name="source">The DataContract object to serialize.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array that may be present in the object graph.</param>
        /// <returns>Bytes representation of the source DataContract object.</returns>
        public static byte[] SerializeDataContractBinary(this object source, Type[] knownTypes = null)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            DataContractSerializer dataContractSerializer = (knownTypes == null || knownTypes.Length == 0) ? new DataContractSerializer(source.GetType()) : new DataContractSerializer(source.GetType(), knownTypes);

            using (MemoryStream memoryStream = new MemoryStream())
            {
                dataContractSerializer.WriteObject(memoryStream, source);
                memoryStream.Position = 0;
                return memoryStream.ToArray();
            }
        }

        /// <summary>
        /// Deserializes DataContract bytes to object.
        /// </summary>
        /// <param name="source">The bytes to deserialize.</param>
        /// <param name="type">Type of DataContract object.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array that may be present in the object graph.</param>
        /// <returns>Instance of DataContract object.</returns>
        public static object DeserializeDataContractBinary(this byte[] source, Type type, Type[] knownTypes = null)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (type == null)
            {
                throw new ArgumentNullException("type");
            }

            DataContractSerializer dataContractSerializer = (knownTypes == null || knownTypes.Length == 0) ? new DataContractSerializer(type) : new DataContractSerializer(type, knownTypes);

            using (MemoryStream memoryStream = new MemoryStream(source))
            {
                memoryStream.Position = 0;
                return dataContractSerializer.ReadObject(memoryStream);
            }
        }

        /// <summary>
        /// Deserializes DataContract bytes to object.
        /// </summary>
        /// <param name="source">The bytes to deserialize.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array of object types to serialize.</param>
        /// <returns>Instance of DataContract object.</returns>
        [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "Reviewed.")]
        public static object DeserializeDataContractBinary(this byte[] source, Type[] knownTypes = null)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            if (knownTypes == null || knownTypes.Length < 1)
            {
                throw new ArgumentException("knownTypes is null or empty.", "knownTypes");
            }

            Type sourceType = null;

            MemoryStream memoryStream = new MemoryStream(source);
            memoryStream.Position = 0;

            using (XmlReader xmlReader = XmlReader.Create(memoryStream))
            {
                string rootNodeName = XElement.Load(xmlReader).Name.LocalName;

                sourceType = knownTypes.FirstOrDefault(p => p.Name == rootNodeName);

                if (sourceType == null)
                {
                    throw new InvalidOperationException();
                }

                memoryStream.Position = 0;
                DataContractSerializer dataContractSerializer = new DataContractSerializer(sourceType, knownTypes);
                return dataContractSerializer.ReadObject(memoryStream);
            }
        }

        /// <summary>
        /// Deserializes DataContract bytes to object.
        /// </summary>
        /// <typeparam name="T">Type of the returns object.</typeparam>
        /// <param name="source">The bytes to deserialize.</param>
        /// <param name="knownTypes">A <see cref="T:System.Type" /> array that may be present in the object graph.</param>
        /// <returns>Instance of DataContract object.</returns>
        public static T DeserializeDataContractBinary<T>(this byte[] source, Type[] knownTypes = null)
        {
            if (source == null)
            {
                throw new ArgumentNullException("source");
            }

            DataContractSerializer dataContractSerializer = (knownTypes == null || knownTypes.Length == 0) ? new DataContractSerializer(typeof(T)) : new DataContractSerializer(typeof(T), knownTypes);

            using (MemoryStream memoryStream = new MemoryStream(source))
            {
                memoryStream.Position = 0;
                return (T)dataContractSerializer.ReadObject(memoryStream);
            }
        }
        #endregion
    }
}
